import os
import glob
import re
import requests
from PyPDF2 import PdfReader
from fpdf import FPDF
import time
from datetime import datetime
import warnings
from typing import Dict, Optional

# 禁用fpdf的字体警告
warnings.filterwarnings("ignore", category=UserWarning, module="fpdf.ttfonts")


class PDFSummarizer:
    def __init__(self):
        """初始化R1模型分析器"""
        # R1专用配置
        self.base_url = "https://api.deepseek.com/v1"  # R1基础端点
        self.model = "deepseek-reasoner"  # R1模型名称
        self.api_key = os.environ.get("DEEPSEEK_API_KEY")
        self.max_retries = 3
        self.timeout = 90

        # 字体配置
        self.font_path, self.font_name = self._configure_font()

    def _configure_font(self) -> tuple:
        """配置中文字体返回 (字体路径, 字体名称)"""
        font_candidates = [
            ("msyh.ttf", "MicrosoftYaHei"),  # 微软雅黑
            ("simhei.ttf", "SimHei"),  # 黑体
            ("arial.ttf", "Arial")  # 英文备用
        ]

        fonts_dir = "C:/Windows/Fonts/"
        for filename, name in font_candidates:
            path = os.path.join(fonts_dir, filename)
            if os.path.exists(path):
                return path, name
        return None, "Arial"

    def extract_text_from_pdf(self, pdf_path: str) -> str:
        """从PDF提取文本内容（与之前相同）"""
        text = []
        try:
            with open(pdf_path, 'rb') as file:
                reader = PdfReader(file)
                for page in reader.pages:
                    if page_text := page.extract_text():
                        cleaned = re.sub(r'[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF]', ' ', page_text)
                        text.append(cleaned)
            return '\n'.join(text).strip()
        except Exception as e:
            print(f"PDF提取失败 [{pdf_path}]: {str(e)}")
            return ""

    def summarize_with_r1(self, text: str, filename: str) -> str:
        """调用DeepSeek R1模型进行推理分析"""
        if not text.strip():
            return "无有效文本内容"

        # R1专用提示词（优化用于推理分析）
        prompt = f"""作为行业分析师，请从年报中提取结构化信息：

        # 核心推理分析
        ## 行业竞争态势
        - 光伏行业竞争格局：[分析]
        - 风电行业技术壁垒：[分析]

        ## 财务健康度评估
        - 营收增长可持续性：{'是/否，依据...'}
        - 研发投入效益比：{'X:1 (说明...)'}

        ## 战略风险预测
        - 主要风险点：[列出]
        - 应对措施有效性评估：[分析]

        文件: {filename}
        内容摘要:
        {text[:15000]}  # 控制输入长度
        """

        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
            "X-Model-Type": "reasoner"  # R1可能需要特殊头
        }

        payload = {
            "model": self.model,
            "messages": [{"role": "user", "content": prompt}],
            "temperature": 0.2,  # R1推荐更低随机性
            "max_tokens": 3000,
            "top_p": 0.9
        }

        for attempt in range(self.max_retries):
            try:
                response = requests.post(
                    f"{self.base_url}/chat/completions",  # R1可能使用标准端点
                    headers=headers,
                    json=payload,
                    timeout=self.timeout
                )

                # 调试信息（实际使用时可以移除）
                print(f"R1响应状态码: {response.status_code}")
                if response.status_code != 200:
                    print(f"R1响应内容: {response.text[:300]}")

                response.raise_for_status()
                return response.json()["choices"][0]["message"]["content"]

            except requests.exceptions.HTTPError as e:
                print(f"R1 API请求失败 [{attempt + 1}/{self.max_retries}]: {str(e)}")
                if response.status_code == 429:
                    wait = int(response.headers.get("Retry-After", 10))
                    time.sleep(wait)
                elif response.status_code == 404:
                    print("错误: 模型端点不存在，请确认base_url配置")
                    break
            except Exception as e:
                print(f"R1请求异常: {type(e).__name__} - {str(e)}")
                time.sleep(5)

        return "R1模型分析失败"

    def create_summary_pdf(self, summaries: Dict[str, str], output_path: str) -> bool:
        """生成PDF报告（与之前相同）"""
        pdf = FPDF()
        pdf.set_auto_page_break(auto=True, margin=15)

        try:
            if self.font_path:
                pdf.add_font(self.font_name, '', self.font_path, uni=True)
                pdf.add_font(self.font_name, 'B', self.font_path, uni=True)
        except:
            self.font_name = "Arial"

        # 封面页
        pdf.add_page()
        pdf.set_font(self.font_name, 'B', 24)
        pdf.cell(0, 40, "新能源行业深度分析(R1版)", 0, 1, 'C')
        pdf.set_font(self.font_name, '', 16)
        pdf.cell(0, 20, datetime.now().strftime('生成日期: %Y-%m-%d'), 0, 1, 'C')
        pdf.ln(30)

        # 内容页
        for filename, content in summaries.items():
            pdf.add_page()
            pdf.set_font(self.font_name, 'B', 16)
            pdf.cell(0, 10, f"R1分析报告: {filename}", 0, 1)

            pdf.set_font(self.font_name, '', 12)
            for line in content.split('\n'):
                if line.startswith('## '):
                    pdf.set_font(self.font_name, 'B', 14)
                    pdf.cell(0, 8, line[3:].strip(), 0, 1)
                    pdf.set_font(self.font_name, '', 12)
                elif line.startswith('- '):
                    pdf.cell(10)
                    pdf.multi_cell(0, 6, line[2:].strip())
                else:
                    pdf.multi_cell(0, 6, line)
                pdf.ln(2)

        try:
            pdf.output(output_path)
            return True
        except Exception as e:
            print(f"PDF保存失败: {str(e)}")
            return False

    def process_directory(self, input_dir: str) -> Optional[Dict[str, str]]:
        """处理目录中的所有PDF文件（与之前相同）"""
        if not os.path.isdir(input_dir):
            print(f"目录不存在: {input_dir}")
            return None

        pdf_files = glob.glob(os.path.join(input_dir, "*.pdf"))
        if not pdf_files:
            print(f"未找到PDF文件: {input_dir}")
            return None

        results = {}
        for pdf_file in pdf_files:
            filename = os.path.basename(pdf_file)
            print(f"\n处理中: {filename}")

            try:
                text = self.extract_text_from_pdf(pdf_file)
                if not text:
                    print("-> 无有效文本")
                    results[filename] = "内容提取失败"
                    continue

                summary = self.summarize_with_r1(text, filename)
                results[filename] = summary

                # 打印摘要预览
                print("-> R1分析完成")
                print("\n".join(summary.split('\n')[:10]) + "\n...")

            except Exception as e:
                print(f"-> 处理失败: {str(e)}")
                results[filename] = f"R1处理错误: {str(e)}"

        return results if results else None


if __name__ == "__main__":
    # 配置路径
    INPUT_DIR = r"d:\pycharmprojects\pythonproject\阳光电源年报"
    OUTPUT_DIR = r"C:\temp"
    OUTPUT_FILE = "新能源行业R1分析报告.pdf"

    # 检查环境变量
    if not os.environ.get("DEEPSEEK_API_KEY"):
        print("错误: 请设置DEEPSEEK_API_KEY环境变量")
        exit(1)

    # 确保输出目录存在
    os.makedirs(OUTPUT_DIR, exist_ok=True)

    # 运行分析
    analyzer = PDFSummarizer()
    print("\n" + "=" * 50)
    print("DeepSeek R1 年报分析系统".center(50))
    print("=" * 50 + "\n")

    summaries = analyzer.process_directory(INPUT_DIR)

    if summaries:
        output_path = os.path.join(OUTPUT_DIR, OUTPUT_FILE)
        if analyzer.create_summary_pdf(summaries, output_path):
            print(f"\nR1分析报告已保存至: {output_path}")
    else:
        print("\n未生成有效分析结果")

    print("\n分析流程结束")